

`include "defines.v"

module mem_stage(
  //input wire rst,
  //input wire [4 : 0]inst_type_i,
  //input wire [7 : 0]inst_opcode,
  //input wire [`REG_BUS]alu_result,
  //input wire [`REG_BUS]op2,
  
  //output reg [4 : 0]inst_type_o,
  ///output reg  [`REG_BUS]rd_data,

  input wire rst,
  input wire [4:0]inst_type_i,
  input wire rd_w_ena_i,
  input wire [4:0]rd_w_addr_i,
  input wire l_mem_i,
  input wire s_mem_i,
  input wire [1:0]datasize_i,
  input wire unsigned_load_i,
  input wire [`REG_BUS]rs2_data_i,
  input [`REG_BUS]alu_result_i,
  input wire [31:0]inst_i,
  input wire [`REG_BUS]pc_i,


  //from ram
  input wire [`REG_BUS]data_loaded,
  input wire data_valid,


  //to ram
  output reg [1:0]datasize_2ram,
  output wire load_en_2ram,
  output wire save_en_2ram,
  output reg [`REG_BUS]data_2ram,
  output reg [`REG_BUS]addr_2ram,

  //pass
  output wire [4:0]inst_type_o,
  output wire rd_w_ena_o,
  output wire [4:0]rd_w_addr_o,
  output reg [`REG_BUS]rd_w_data,
  output wire [31:0]inst_o,
  output wire [`REG_BUS]pc_o
);

assign inst_type_o = inst_type_i;
assign rd_w_ena_o = rd_w_ena_i;
assign rd_w_addr_o = rd_w_addr_i;
assign inst_o = inst_i;
assign pc_o = pc_i;

always @(*) begin   //determine whether the data writen to register is from ram or alu
  if (rst==1'b1) begin
    rd_w_data = `ZERO_WORD;
  end
  else begin
    if ((l_mem_i==1'b1) && (data_valid==1'b1)) begin  //if load from ram
      //rd_w_data = (data_valid==1'b1)? data_loaded:0;
      if (unsigned_load_i == 1'b1) begin   //unsigned load
        case (datasize_i)
          2'b00: begin  //byte
            rd_w_data = {{56{1'b0}},data_loaded[7:0]};
          end
          2'b01: begin  //half word
            rd_w_data = {{48{1'b0}},data_loaded[15:0]};
          end
          2'b10: begin  //word
            rd_w_data = {{32{1'b0}},data_loaded[31:0]};
          end
          2'b11: begin   //double words
            rd_w_data = data_loaded;
          end
        endcase 
      end
      else begin   //signed load
        case (datasize_i)
          2'b00: begin  //byte
            rd_w_data = {{56{data_loaded[7]}},data_loaded[7:0]};
          end
          2'b01: begin  //half word
            rd_w_data = {{48{data_loaded[15]}},data_loaded[15:0]};
          end
          2'b10: begin  //word
            rd_w_data = {{32{data_loaded[31]}},data_loaded[31:0]};
          end
          2'b11: begin   //double words
            rd_w_data = data_loaded;
          end
        endcase
      end

    end
    else begin  //if not load from ram
      rd_w_data = alu_result_i;
    end
  end
end

assign addr_2ram = alu_result_i;  //address to ram is always from alu
assign datasize_2ram = datasize_i;
assign data_2ram = rs2_data_i;  //data to ram is always form rs2
assign load_en_2ram = (rst==1'b1)? 1'b0 : l_mem_i;
assign save_en_2ram = (rst==1'b1)? 1'b0 : s_mem_i;

/*
always @(*) begin    //only whole byte save
  if (rst==1'b1) begin
    save_valid_2ram = 1'b0;
  end
  else begin
    if (s_mem_i==1'b1) begin
      save_valid_2ram = 1'b1;
    end
    else begin
      save_valid_2ram = 1'b0;
    end
  end
end
*/



endmodule
